package com.dymall.user.service.impl;

import cn.hutool.core.lang.Validator;
import cn.hutool.db.DbRuntimeException;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dymall.common.api.AuthClient;
import com.dymall.common.exception.BadRequestException;
import com.dymall.common.exception.BizIllegalException;
import com.dymall.common.exception.CommonException;
import com.dymall.common.exception.ForbiddenException;
import com.dymall.common.util.UserContext;
import com.dymall.user.domain.dto.req.RegisterReq;
import com.dymall.user.domain.dto.req.UserInfoResp;
import com.dymall.user.domain.dto.resp.RegisterResp;
import com.dymall.user.domain.dto.req.LoginReq;
import com.dymall.user.domain.po.User;
import com.dymall.user.domain.dto.resp.LoginResp;
import com.dymall.user.enums.UserStatus;
import com.dymall.user.mapper.UserMapper;
import com.dymall.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;


@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    private final UserMapper userMapper;

    private final PasswordEncoder passwordEncoder;

    private final AuthClient authClient;

    @Override
    public LoginResp login(LoginReq loginDTO) {
        // 1.数据校验
        String email = loginDTO.getEmail();
        String password = loginDTO.getPassword();

        // 2.根据邮箱查询
        User user = lambdaQuery().eq(User::getEmail, email).one();
//        Assert.notNull(user, "邮箱错误");
        if(user == null){
            throw new BadRequestException("邮箱未注册");
        }
        // 3.校验是否禁用
        if (user.getStatus() == UserStatus.FROZEN) {
            throw new ForbiddenException("用户被冻结");
        }
        // 4.校验密码
        if (!passwordEncoder.matches(password, user.getPassword())) {
            throw new BadRequestException("邮箱或密码错误");
        }
        // 5.生成TOKEN
        String token = null;
        try {
            token = authClient.generateToken(user.getId());
        } catch (Exception e) {
            throw new CommonException("token生成失败，服务器内部异常",500);
        }

        // 6.封装VO返回
        LoginResp vo = new LoginResp();
        vo.setUserId(user.getId());
        vo.setEmail(user.getEmail());
        vo.setBalance(user.getBalance());
        vo.setToken(token);
        return vo;
    }

    @Override
    public void deductMoney(String pw, Integer totalFee) {
        log.info("开始扣款");
        // 1.校验密码
        System.out.println("UserContext："+UserContext.getUser());
        User user = getById(UserContext.getUser());
        System.out.println("用户："+user);
        if(user == null || !passwordEncoder.matches(pw, user.getPassword())){
            // 密码错误
            throw new BizIllegalException("用户密码错误");
        }

        // 2.尝试扣款
        try {
            baseMapper.updateMoney(UserContext.getUser(), totalFee);
        } catch (Exception e) {
            throw new BadRequestException("扣款失败，可能是余额不足！", e);
        }
        log.info("扣款成功");
    }

    @Override
    public Integer getBalanceByUserId(Long id) {
        User user = userMapper.selectById(id);
        if(user == null){
            throw new BadRequestException("用户不存在");
        }
        return user.getBalance();
    }

    @Override
    public UserInfoResp getUserInfo(Long userId) {
        User user = userMapper.selectById(userId);
        if(user == null){
            throw new BadRequestException("用户未登录");
        }
        UserInfoResp resp = new UserInfoResp();
        resp.setEmail(user.getEmail());
        resp.setPhone(user.getPhone());
        resp.setStatus(String.valueOf(user.getStatus()));

        return resp;
    }

    @Override
    public RegisterResp register(RegisterReq registerReq) {
        // 1. 校验请求数据
        String email = registerReq.getEmail();
        if(!Validator.isEmail(email)){
            throw new BadRequestException("邮箱不合法");
        }

        String password = registerReq.getPassword();
        Assert.hasText(password, "密码不能为空");

        // 2. 判断用户名是否已存在
        User existingUser = lambdaQuery().eq(User::getEmail, email).one();
        if (existingUser != null) {
            throw new BadRequestException("邮箱已存在");
        }

        // 3. 对密码进行加密处理
        String encryptedPassword = passwordEncoder.encode(password);

        // 4. 创建新用户对象并保存
        User user = new User();
        user.setEmail(email);
        user.setPassword(encryptedPassword);
        user.setPhone(registerReq.getPhone());
        user.setStatus(UserStatus.NORMAL);  // 默认为激活状态

        // 保存用户信息
        boolean saved = save(user);
        if (!saved) {
            throw new DbRuntimeException("注册失败，请稍后再试");
        }

        // 5. 返回注册响应
        RegisterResp registerResp = new RegisterResp();
        registerResp.setUserId(user.getId());   // 保存成功自动返回id

        return registerResp;
    }
}
